package foundation.SurModel;

import Jama.Matrix;
import abstractGA.result.ChromOut;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * load the example data from database into Matrices, and save predict data to
 * database
 */
public class InOut {
	
	
	
	/**
	 * Load data
	 * 
	 * @param frmNum:按运行时间排序后开始取的记录（最近的排最前面，从0开始）
	 * @param toNum:
	 *            取多少个染色体数据
	 * @return [X, Y],其中X和Y分别表示输入(14位)和输出(目前仅1位响应时间)
	 */
	public static Matrix[] load(String runID, int frmNum, int count,String sql) {
		SMDAO dao = new SMDAO();
		ArrayList<double[]> inputsList = new ArrayList<double[]>();
		ArrayList<double[]> outputsList = new ArrayList<double[]>();
		List<ChromOut> chromOuts = dao.getLatestChroms(runID, frmNum, count,sql);
		int size = chromOuts.size();// 样本数
		double maxVal = Double.MIN_VALUE;// 379.59601d;
		double minVal = Double.MAX_VALUE;// 1.85845;
		// 取每一个染色体数据，解析成14个输入变量值和1个输出响应时间
		for (ChromOut chromOut : chromOuts) {
			String code = chromOut.getCodes();

			double[] in = toDblcodes(code);// 解成dbl编码
			in = postDblCodePros(in);// 将未使用处理器主频为0
			// in = dblCodeTran(in);// 将编码各位变换到[-1,1]

			double[] out = new double[1];
			out[0] = chromOut.getObjVal1() + 0d;// 输出值

			if (Double.compare(out[0], maxVal) > 0) {// 比最大值大
				maxVal = out[0];
			}
			if (Double.compare(out[0], minVal) < 0) {// 比最小值小
				minVal = out[0];
			}

			inputsList.add(in);
			outputsList.add(out);
		}

		double[][] inmatVal = new double[size][14];
		double[][] outmatVal = new double[size][1];
		inputsList.toArray(inmatVal);
		outputsList.toArray(outmatVal);
	//	outmatVal = YTran(outmatVal, minVal, maxVal);// 将输出变换到[-1,1]上

		//System.out.println("min=" + minVal + ",max=" + maxVal);

		/*
		 * for(int i=0;i<size;i++){ outmatVal[i][0]=1d/outmatVal[i][0]; }
		 */

		return new Matrix[] { new Matrix(inmatVal), new Matrix(outmatVal) };
	}
	
	public static ArrayList<ArrayList<Double>> loadr(String runID, int frmNum, int count,String sql) {
		ArrayList<ArrayList<Double>> datas = new ArrayList<ArrayList<Double>>();
		SMDAO dao = new SMDAO();
		ArrayList<double[]> inputsList = new ArrayList<double[]>();
		ArrayList<double[]> outputsList = new ArrayList<double[]>();
		List<ChromOut> chromOuts = dao.getLatestChroms(runID, frmNum, count,sql);
		
		int size = chromOuts.size();// 样本数
		double maxVal = Double.MIN_VALUE;// 379.59601d;
		double minVal = Double.MAX_VALUE;// 1.85845;
		// 取每一个染色体数据，解析成14个输入变量值和1个输出响应时间
		for (ChromOut chromOut : chromOuts) {
			String code = chromOut.getCodes();
			
			
			double[] in = toDblcodes(code);// 解成dbl编码
//			in = postDblCodePros(in);// 将未使用处理器主频为0
			// in = dblCodeTran(in);// 将编码各位变换到[-1,1]

			double[] out = new double[1];
			out[0] = chromOut.getObjVal1() + 0d;// 输出值

			if (Double.compare(out[0], maxVal) > 0) {// 比最大值大
				maxVal = out[0];
			}
			if (Double.compare(out[0], minVal) < 0) {// 比最小值小
				minVal = out[0];
			} 

			inputsList.add(in);
			outputsList.add(out);
		}
		
		
		
		for(int i=0;i<size;i++){
			ArrayList<Double> data = new ArrayList<>();
			for(int j=0;j<15;j++){
				if(j<14){
					data.add(inputsList.get(i)[j]);
				}
				else{
					data.add(outputsList.get(i)[0]);
				}
			}
			System.out.println(data.toString());
			datas.add(data);
		}
		

		return datas;
		
		
	}

	public static double[] toDblcodes(String code) {
		double[] in = new double[14];
		/*
		 * code= [11.3, 8.3, 10.475, 10.700001, 13.175, 7.1000004, 17.6,
		 * 13.55,18.650002, server7, server7, server9, server2, server9,
		 * server9, server3, server9, server9, CoreOnlineEngine,
		 * WebServer2,GraphicalReporting, UserManagement]
		 */
		int len = code.length();
		String tempStr = code.substring(1, len - 1);
		String[] codeStrs = tempStr.split(",");
		for(int j=4;j<13;j++){
			
		}
		
		
		// 解析4位处理器速度
		for (int i = 0; i < 4; i++) {
			in[i] = Double.parseDouble(codeStrs[i].trim());
		}
		// 解析部署
		for (int j = 4; j < 13; j++) {
			String svrNm = codeStrs[j].trim();
			int size = svrNm.length();
			in[j] = Double.parseDouble(svrNm.substring(6, size));
		}
		// 解析组件选择
		String cmpNm = codeStrs[13].trim();
		switch (cmpNm) {
		case "WebServer":
			in[13] = 1d;
			break;
		case "WebServer2":
			in[13] = 2d;
			break;
		case "WebServer3":
			in[13] = 3d;
			break;
		default:
			break;
		}

		return in;
	}

	public static double[] toDlbCodes(List<StringBuffer> codes) {
		int len = codes.size();
		double[] dblCodes = new double[len];
		/*
		 * code= [11.3, 8.3, 10.475, 10.700001, 13.175, 7.1000004, 17.6,
		 * 13.55,18.650002, server7, server7, server9, server2, server9,
		 * server9, server3, server9, server9, CoreOnlineEngine,
		 * WebServer2,GraphicalReporting, UserManagement]
		 */

		// 解析9位处理器速度
		for (int i = 0; i < 4; i++) {
			dblCodes[i] = Double.parseDouble(codes.get(i).toString().trim());
		}
		// 解析部署
		for (int j = 4; j < 13; j++) {
			String svrNm = codes.get(j).toString().trim();
			int size = svrNm.length();
			dblCodes[j] = Double.parseDouble(svrNm.substring(6, size));
		}
		// 解析组件选择
		String cmpNm = codes.get(13).toString().trim();
		switch (cmpNm) {
		case "WebServer":
			dblCodes[13] = 1d;
			break;
		case "WebServer2":
			dblCodes[13] = 2d;
			break;
		case "WebServer3":
			dblCodes[13] = 3d;
			break;
		default:
			break;
		}


		return dblCodes;
	}

	public static double[] postDblCodePros(double[] dblCodes) {
		double[] newDblCodes = new double[14];
		for (int j = 0; j < 14; j++)
			newDblCodes[j] = dblCodes[j];
		boolean[] noClearflags = new boolean[9];
		for (int k = 0; k < 9; k++)
			noClearflags[k] = false;
		for (int k = 9; k < 18; k++) {
			int srvNo = (int) dblCodes[k];
			noClearflags[srvNo - 1] = true;
		}

		for (int i = 0; i < 4; i++) {
			if (!noClearflags[i]) {
				newDblCodes[i] = 0d;
			}
		}

		return newDblCodes;
	}

	public static double[] dblCodeTran(double[] dblCodes) {
		double[] newDblCodes = new double[14];
		for (int i = 0; i < 9; i++) {// 处理器速度
			double temp = dblCodes[i];
			if (Double.compare(0d, temp) != 0) {
				double speedTran = ((2d * temp) / 15d) - (5d / 3d);
				newDblCodes[i] = speedTran;
			}
		}

		for (int j = 9; j < 18; j++) {// 部署
			double deplTran = (dblCodes[j] - 5d) / 4d;
			newDblCodes[j] = deplTran;
		}
		// 组件选择

		double cmpSelTran = (2d * dblCodes[18]) - 3d;
		newDblCodes[18] = cmpSelTran;

		cmpSelTran = dblCodes[19] - 2d;
		newDblCodes[19] = cmpSelTran;

		cmpSelTran = (2d * dblCodes[20]) - 3d;
		newDblCodes[20] = cmpSelTran;

		cmpSelTran = (2d * dblCodes[21]) - 3d;
		newDblCodes[21] = cmpSelTran;

		return newDblCodes;
	}

	public static double[] restoreOriCode(double[] dblCodes) {
		double[] newDblCodes = new double[14];
		for (int i = 0; i < 9; i++) {// 处理器速度
			double temp = dblCodes[i];
			if (Double.compare(0d, temp) != 0) {
				double speed = (7.5d * temp) + 12.5d;
				newDblCodes[i] = speed;
			}

		}

		for (int j = 9; j < 18; j++) {// 部署
			double depl = 4d * dblCodes[j] + 5d;
			newDblCodes[j] = depl;
		}

		// 组件选择
		double cmpSel = (3d + dblCodes[18]) / 2d;
		newDblCodes[18] = cmpSel;

		cmpSel = dblCodes[19] + 2d;
		newDblCodes[19] = cmpSel;

		cmpSel = (3d + dblCodes[20]) / 2d;
		newDblCodes[20] = cmpSel;

		cmpSel = (3d + dblCodes[21]) / 2d;
		newDblCodes[21] = cmpSel;

		return newDblCodes;
	}

	public static double[][] YTran(double[][] Y, double minVal, double maxVal) {
		boolean isExp = false;
		int rowSize = Y.length;
		double[][] newY = new double[rowSize][1];
		if (rowSize > 0) {
			int colSize = Y[0].length;
			if (colSize == 1) {
				double factor = maxVal - minVal;
				for (int i = 0; i < rowSize; i++) {// 将输出值线性变换到[-1,1]中
					double temp = Y[i][0];
					newY[i][0] = (2 * (temp - minVal) - factor) / factor;
				}
			} else {
				isExp = true;
			}
		} else {
			isExp = true;
		}
		if (isExp) {
			throw new IllegalArgumentException("Y的行列数不正确！");
		}
		return newY;
	}

	public static double[][] restoreY(double[][] YTran, double minVal, double maxVal) {
		int rowSize = YTran.length;
		double[][] Y = new double[rowSize][1];
		boolean isExp = false;
		if (rowSize > 0) {
			int colSize = YTran[0].length;
			if (colSize == 1) {
				double k = maxVal - minVal;
				for (int i = 0; i < rowSize; i++) {
					Y[i][0] = 0.5 * (YTran[i][0] + 1) * k + minVal;
				}
			} else {
				isExp = true;
			}
		} else {
			isExp = true;
		}
		if (isExp) {
			throw new IllegalArgumentException("Y的行列数不正确！");
		}
		return Y;
	}

	public static String toStrCode(double[] dblCodes) {

		String codeStrs = "[";
		// int size=dblCodes.length;
		// 处理器速度
		for (int i = 0; i < 9; i++) {
			if (i > 0) {
				codeStrs += ", " + String.valueOf(dblCodes[i]);
			} else {
				codeStrs += String.valueOf(dblCodes[i]);
			}
		}
		// 组件部署
		for (int j = 9; j < 18; j++) {
			int srvNo = (int) dblCodes[j];
			String srvNm = ", server" + String.valueOf(srvNo);
			codeStrs += srvNm;
		}
		// 组件选择
		// 解析组件选择
		int cmpNo = (int) dblCodes[18];
		if (cmpNo == 1) {
			codeStrs += ", CoreOnlineEngine";
		} else {
			codeStrs += ", CoreGraphicEngine";
		}
		cmpNo = (int) dblCodes[19];
		switch (cmpNo) {
		case 1:
			codeStrs += ", WebServer";
			break;
		case 2:
			codeStrs += ", WebServer2";
			break;
		case 3:
			codeStrs += ", WebServer3";
			break;
		default:
			break;
		}

		cmpNo = (int) dblCodes[20];
		if (cmpNo == 1) {
			codeStrs += ", GraphicalReporting";
		} else {
			codeStrs += ", GraphicalReporting2";
		}

		cmpNo = (int) dblCodes[21];
		if (cmpNo == 1) {
			codeStrs += ", UserManagement";
		} else {
			codeStrs += ", UserManagement2";
		}
		codeStrs += "]";
		return codeStrs;
	}

	/**
	 * Simple example of how to use this class.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		Matrix[] data = InOut.load("!!SMDFGA", 100, 100,"");
		
		System.out.println("data.length"+data.length);

		double[][] input = data[0].getArray();
		double[][] output = data[1].getArray();
		// outPredToDB("!!SMDFGA",1, 100, input, output);

		int len = input.length;
		/*
		 * for (int k = 0; k < len; k++) { double[] dblCodes = input[k]; String
		 * strCodes = toStrCode(restoreOriCode(dblCodes));
		 * System.out.println(strCodes); }
		 */

		// double[] dblCodes = output[k];maxVal=379.59601d;minVal=1.85845;
		double maxVal = 112.5530d;
		double minVal = 1.88698;
		double Y[][] = restoreY(output, minVal, maxVal);
		for (int k = 0; k < len; k++)

			System.out.println("rest=" + output[k][0]);

	}
}
